<?php

namespace App\Kuafu\Mybank\Service;

use App\Kuafu\Mybank\Model\MybankOrderRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderRecordWithholdMappingsModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRecordModel;
use App\Kuafu\Mybank\Model\MybankWalletRecordModel;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Library\FeiShu\SendFs;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

/**
 * 协议代扣通知
 */
class MybankOrderWithholdNotifyService
{

    public string $outOrderNo;
    public string $orderNo;
    public string $outTradeNo;
    public string $operateNo;
    public string $finishDate;
    public string $status;
    public string $errorCode;
    public string $errorDesc;

    public Model $withholdModel;

    public function __construct(array $requestBody)
    {
        $requestBody      = array_filter($requestBody);
        $this->outOrderNo = $requestBody['OutTradeNo'];
        $this->orderNo    = $requestBody['OrderNo'];
        $this->outTradeNo = $requestBody['OutTradeNo'];
        $this->operateNo  = $requestBody['OperateNo'];
        $this->finishDate = $requestBody['FinishDate'] ?? '';
        $this->status     = $requestBody['Status'];
        $this->errorCode  = $requestBody['ErrorCode'] ?? '';
        $this->errorDesc  = $requestBody['ErrorDesc'] ?? '';

        $this->initWithholdRecordInfo();
    }


    /**
     * @return void
     */
    public function initWithholdRecordInfo()
    {
        $model = MybankOrderWithholdRecordModel::query()
                                               ->where('outTradeNo', $this->outTradeNo)
                                               ->with(['billRecordRel', 'orderWithholdMappings'])
                                               ->first();

        if (empty($model)) {
            // TODO 判断不存在的订单抛出异常
        }

        $this->withholdModel = $model;
    }

    /**
     * @return array|void
     * @throws GuzzleException
     * @throws \App\Exceptions\BaseException
     */

    public function handle()
    {
        // 是否存在
        if (empty($this->withholdModel)) {
            // TODO 记录异常
            return;
        }

        // 幂等状态判断
        if ($this->isHandled()) {
            return;
        }

        // 更新数据库记录状态
        $this->updateWithholdRecordData();

        // 协议代扣是否完成
        if (!($this->isPaid())) {
            return;
        }

        // 获取余额
        $withholdV2Service = (new MybankOrderWithholdV2Service(0, $this->withholdModel->payerId));

        // 计算总支付金额
        $totalAmount          = $this->withholdModel->totalAmount;
        $totalFreezeAmount    = $this->withholdModel->freezeAmount;
        $totalAvailableAmount = $this->withholdModel->availableAmount;

        // 更新对应订单记录金额
        foreach ($this->withholdModel->orderWithholdMappings as $orderWithholdMapping) {
            if (!$orderWithholdMapping->orderRecordRel) {
                continue;
            }

            // 计算这个账单总支付的金额， 更新对应的账单记录
            $payTotalSum = $this->getTotalPaidOrderAmount($orderWithholdMapping->orderRecordId);

            // TODO 已支付金额 大于 待支付金额为异常

            $orderWithholdMapping->orderRecordRel->paidBrokerage = $payTotalSum;
            $orderWithholdMapping->orderRecordRel->netPaidAmount = $payTotalSum;
            // 支付完成
            if ($orderWithholdMapping->orderRecordRel->paidBrokerage == $orderWithholdMapping->orderRecordRel->brokerage) {
                $orderWithholdMapping->orderRecordRel->completeAt = time();
                $orderWithholdMapping->orderRecordRel->payStatus  = MybankOrderRecordModel::PAY_STATUS_PAID;
            } else {
                $orderWithholdMapping->orderRecordRel->payStatus = MybankOrderRecordModel::PAY_STATUS_PAYING;
            }
            $orderWithholdMapping->orderRecordRel->save();

            /**
             * 该订单支付完成后的操作
             */
            if ($orderWithholdMapping->orderRecordRel->payStatus == MybankOrderRecordModel::PAY_STATUS_PAID) {
                // 钱包添加协议代扣的记录
                MybankOrderWithholdService::walletRecordAdd(
                    $this->withholdModel->payerId,
                    MybankWalletRecordModel::PAY_TRANS_TYPE,
                    $this->withholdModel->totalAmount,
                    $withholdV2Service->getMerchantBalance(),
                    $orderWithholdMapping->orderRecordRel->shopId,
                    $this->withholdModel->id,
                    MybankWalletRecordModel::RECORD_ID_TYPE_WITHHOLD,
                    MybankWalletRecordModel::PLATFORM_TYPE_DEFAULT,
                    MybankOrderRecordModel::WALLET_TYPE_SHOW_TYPE_TEXT[$orderWithholdMapping->orderRecordRel->type],
                    $this->withholdModel->orderNo,
                    '',
                    $this->withholdModel->finishDateTime,
                    MybankWalletRecordModel::SUCCESS_STATUS,
                    MybankWalletRecordModel::SHOW_RECORD
                );

                // 余额解冻
//                $withholdModel = $this->withholdModel;
//                dispatch(function () use ($withholdV2Service, $withholdModel) {
//                    // 防止重复
//                    sleep(10);
//                    MybankOrderWithholdService::unfreezeBalance(
//                        $withholdV2Service->getBalanceFreeze(),
//                        $withholdModel
//                    );
//                })->delay(now()->addMinutes(5))->onQueue('{QUEUE-RMS-API-MYBANK-DEFAULT}');

                /**
                 * 支付成功后的业务处理
                 */

                // 分账订单不走这块业务处理
                if (in_array($orderWithholdMapping->orderRecordRel->type,
                    MybankOrderRecordModel::TYPE_SEPARATE_BILL_TYPE)) {
                    // TODO 分账业务支付成功

                } else {
                    // 非分账业务
                    try {
                        // 支付成功 - pay_stream联动
                        PayService::sPayCallBackLog(PayStreamModel::PAY_CHANNEL_MYBANK_PAY,
                            ['payNo' => $orderWithholdMapping->orderRecordRel->tranId]);
                    } catch (Exception $exception) {
                        Log::channel('mybank')->error('支付成功 - pay_stream联动错误', [
                            'msg'  => $exception->getMessage(),
                            'code' => $exception->getCode(),
                            'line' => $exception->getLine(),
                            'file' => $exception->getFile(),
                        ]);
                    }
                }
            }
        }

        return [ResponseAlias::HTTP_OK, []];
    }

    /**
     * 是否已经处理
     *
     * @return bool
     */
    private function isHandled(): bool
    {
        // 判断是否已经处理过了
        if (in_array($this->withholdModel->status, [
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS
        ])) {
            return true;
        }

        return false;
    }

    /**
     * 更新数据库记录
     *
     * @return void
     */
    private function updateWithholdRecordData()
    {
        // 更新代扣记录状态
        $this->withholdModel->outOrderNo = $this->outOrderNo;
        $this->withholdModel->orderNo    = $this->orderNo;
        $this->withholdModel->operateNo  = $this->operateNo;

        if ($this->isPaid()) {
            $this->withholdModel->finishDateTime = strtotime($this->finishDate);
            $this->withholdModel->status         = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS;
        } else {
            $this->withholdModel->status    = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL;
            $this->withholdModel->errorCode = $this->errorCode;
            $this->withholdModel->errorDesc = $this->errorDesc;

            logMsg('协议代扣通知异常', [
                'msg' => $this->errorDesc,

            ], true, true, SendFs::ROBOT_BATCH_BILL_MATCH);

        }

        $this->withholdModel->save();
    }

    /**
     * 是否支付
     *
     * @return bool
     */
    private function isPaid(): bool
    {
        if ($this->status == 'SUCCESS' && !empty($this->finishDate)) {
            return true;
        }
        return false;
    }


    /**
     * 获取账单总支付金额
     *
     * @param string $orderRecordId
     * @return int|mixed
     */
    private function getTotalPaidOrderAmount(string $orderRecordId)
    {
        $payTotalSum = 0;
        MybankOrderRecordWithholdMappingsModel::query()
                                              ->where('orderRecordId', $orderRecordId)
                                              ->with([
                                                  'orderWithholdRecordRel' => function ($query) {
                                                      $query
                                                          ->select(['id', 'outTradeNo', 'status'])
                                                          ->where('status',
                                                              MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS);
                                                  }
                                              ])
                                              ->get()
                                              ->each(function ($payItem) use (&$payTotalSum) {
                                                  if (!empty($payItem->orderWithholdRecordRel)) {
                                                      $payTotalSum += $payItem->amount;
                                                  }
                                              });

        return $payTotalSum;
    }

    private function updateOrderRecord(Model $orderWithholdMapping, $payTotalSum)
    {
        $orderWithholdMapping->orderRecordRel->paidBrokerage = $payTotalSum;
        $orderWithholdMapping->orderRecordRel->netPaidAmount = $payTotalSum;
        // 支付完成
        if ($orderWithholdMapping->orderRecordRel->paidBrokerage == $orderWithholdMapping->orderRecordRel->brokerage) {
            $orderWithholdMapping->orderRecordRel->completeAt = time();
            $orderWithholdMapping->orderRecordRel->payStatus  = MybankOrderRecordModel::PAY_STATUS_PAID;
        } else {
            $orderWithholdMapping->orderRecordRel->payStatus = MybankOrderRecordModel::PAY_STATUS_PAYING;
        }
        $orderWithholdMapping->orderRecordRel->save();

    }
}
